#pragma once
#include <iostream>
#include <bitset>
#include <array>
#include <algorithm>

/**
 * @example:
 * constexpr uint8_t fft_layers = 10;
 * mem32array<fft_layers> mem0 = {0};
 * mem32array<fft_layers> mem1 = shuffle<fft_layers>(mem0);
 */

template<uint8_t fft_layers, uint32_t fft_points = 1 << fft_layers>
using mem32array = std::array<uint32_t, fft_points>;

template<uint8_t fft_layers, uint64_t fft_points = 1 << fft_layers>
using mem64array = std::array<uint64_t, fft_points>;

template<uint8_t fft_layers>
using bits = std::bitset<fft_layers>;

template<uint8_t bit_len>
bits<bit_len> reverseBits(bits<bit_len> in_bits)
{
  std::string in_string(in_bits.to_string());
  std::reverse(in_string.begin(), in_string.end());
  return bits<bit_len>(in_string);
}

// 按idx reverse 调换数据
template<uint8_t fft_layers, uint32_t fft_points = 1 << fft_layers>
mem32array<fft_layers> shuffle(const mem32array<fft_layers>& mem_array)
{
  mem32array<fft_layers> mem_shuffled;
  for (size_t i=0; i<fft_points; ++i) {
    mem_shuffled[reverseBits<fft_layers>(i).to_ulong()]=mem_array[i];
  }
  return mem_shuffled;
}
